package cn.wenxin.utils;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

public class ExcelUtils {

    private static final Logger logger = LoggerFactory.getLogger(ExcelUtils.class);

    /**
     * 将表转换为对象列表
     *
     * @param workbook      excel文件
     * @param sheetName     表名
     * @param columnNameMap 列跟对象属性的映射关系
     * @param clazz
     * @param <T>
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T> List<T> toObject(Workbook workbook, String sheetName, String[] columnNameMap, Class<T> clazz) throws InstantiationException, IllegalAccessException {
        Sheet sheet = workbook.getSheet(sheetName);
        return toObject(sheet, columnNameMap, clazz);
    }

    /**
     * 将表转换为对象列表
     *
     * @param workbook      excel文件
     * @param sheetIndex    表索引
     * @param columnNameMap 列跟对象属性的映射关系
     * @param clazz
     * @param <T>
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static <T> List<T> toObject(Workbook workbook, int sheetIndex, String[] columnNameMap, Class<T> clazz) throws InstantiationException, IllegalAccessException {
        Sheet sheet = workbook.getSheetAt(sheetIndex);
        return toObject(sheet, columnNameMap, clazz);
    }

    /**
     * 将表转换为对象列表，转换excel的第一张表
     *
     * @param workbook      excel文件
     * @param columnNameMap 列跟对象属性的映射关系
     * @param clazz         类
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> List<T> toObject(Workbook workbook, String[] columnNameMap, Class<T> clazz) throws IllegalAccessException, InstantiationException {
        return toObject(workbook, 0, columnNameMap, clazz);
    }

    /**
     * 将表转换为对象列表
     *
     * @param sheet         excel表
     * @param columnNameMap 列跟对象属性的映射关系
     * @param clazz         类
     * @param <T>
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> List<T> toObject(Sheet sheet, String[] columnNameMap, Class<T> clazz) throws IllegalAccessException, InstantiationException {
        List<T> result = new ArrayList<T>();
        Iterator<Row> rowIterator = sheet.rowIterator();
        //跳过第一行
        rowIterator.next();
        while (rowIterator.hasNext()) {
            Row row = rowIterator.next();
            T t = clazz.newInstance();
            bindValueForObject(row, columnNameMap, t);
            result.add(t);
        }
        return result;
    }

    private static <T> void bindValueForObject(Row row, String[] columnNameMap, T t) {
        for (int index = 0; index < columnNameMap.length; index++) {
            try {
                Field field = null;
                field = t.getClass().getDeclaredField(columnNameMap[index]);
                field.setAccessible(true);
                Class<?> type = field.getType();
                Cell cell = row.getCell(index);
                if (cell == null) {
                    continue;
                }
                String value = cell.toString();
                if (Long.class.equals(type)) {
                    field.set(t, Long.parseLong(value));
                } else if (String.class.equals(type)) {
                    field.set(t, value);
                } else if (Integer.class.equals(type)) {
                    field.set(t, (int) Double.parseDouble(value));
                } else if (Boolean.class.equals(type)) {
                    field.set(t, Boolean.parseBoolean(value));
                } else if (Character.class.equals(type)) {
                    field.set(t, value == null || value == "" ? 0 : value.charAt(0));
                } else if (Double.class.equals(type)) {
                    field.set(t, Double.parseDouble(value));
                } else if (Float.class.equals(type)) {
                    field.set(t, Float.parseFloat(value));
                } else {
                    logger.debug("{}属性类型无法自动赋值: {},坐标:", columnNameMap[index], value, cell.getAddress().formatAsString());
                }
            } catch (NoSuchFieldException e) {
                logger.error("类: {} 找不到属性: {}, 异常", t.getClass().getName(), columnNameMap[index], e);
            } catch (IllegalAccessException e) {
                logger.error("类: {} 属性: {} 赋值异常", t.getClass().getName(), columnNameMap[index], e);
            }
        }
    }

}
